home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.08 Aug 91 / ListHandler Code / CompiledDemo.c next >
Encoding:
C/C++ Source or Header  |  1990-07-29  |  12.9 KB  |  566 lines  |  [TEXT/KAHL]

  1. /*                                            ListDemo.c                                            */
  2. /*
  3.  *
  4.  * Demo my homemade LDEF.  The program lets you open
  5.  * a file and display all of the icons in it.  You
  6.  * can't do anything else, though it would be easy
  7.  * to allow you to copy an icon to the clipboard.
  8.  *
  9.  * Copyright 1990 Martin Minow and MacTutor.
  10.  */
  11. #include "iconicLDEF.h"
  12.  
  13. #define FORMAT    COMPILED                    /* Define  program    */
  14. /*
  15.  * These values configure the demo program: that way
  16.  * we only need to write one piece of code.
  17.  */
  18. #define COMPILED            0
  19. #define    FAKE_RESOURCE    1
  20. #define    TRUE_RESOURCE    2
  21. #if FORMAT == FAKE_RESOURCE || FORMAT == TRUE_RESOURCE
  22. #define LDEF_ID                128
  23. #else
  24. #define LDEF_ID                0                    /* Start with Mac LDEF    */
  25. #endif
  26. #define RESOURCE            'ICN#'
  27. #define iconSize            32                /* Pixels per icon            */
  28. #define sBarWidth            15                /* For grow button            */
  29. #define iconCols             4
  30. #define iconRows             4
  31. #define    hOffsetDelta    16                /* For multiple windows    */
  32. #define vOffsetDelta    0
  33. #define hOffsetMax    (hOffsetDelta * 10)
  34. #define vOffsetMax    (vOffsetDelta * 10)
  35.  
  36. /*
  37.  * Menu organization
  38.  */
  39. enum Menus {
  40.     MENU_Apple            = 1,
  41.     MENU_File                = 256,
  42.     MENU_Edit                = 257
  43. };
  44.  
  45. enum Apple_Menu {
  46.     Apple_About = 1
  47. };
  48.  
  49. enum File_Menu {
  50.     File_Open        = 1,
  51.     File_Close,
  52.     File_DrawAsText,
  53.     File_Debug,
  54.     Unused,
  55.   File_Quit
  56. };
  57.  
  58. #define width(r)        ((r).right - (r).left)
  59. #define height(r)        ((r).bottom - (r).top)
  60.  
  61. /*
  62.  * All the information about a document
  63.  * is stored here.  Note that, when the
  64.  * toolbox selects a window, we can
  65.  * immediately recover the document.
  66.  */
  67. typedef struct {
  68.     WindowRecord    window;
  69.     ListHandle        list;
  70. } DocumentRecord, *DocumentPtr;
  71. /*
  72.  * The current window is always stored in a local
  73.  * WindowPtr variable named "window."  If it's ours,
  74.  * we can access the document by casting window to
  75.  * DocumentPtr and de-referencing it.
  76.  */
  77. #define DOC            (*((DocumentPtr) window))
  78.  
  79. /*
  80.  * isOurWindow is TRUE if its argument is our document.
  81.  */
  82. #define isOurWindow(window)    (                                                        \
  83.             (window) != NIL                                                                        \
  84.         && ((WindowPeek) (window))->windowKind == userKind    \
  85.      )
  86.  
  87. MenuHandle            apple_menu;
  88. MenuHandle            file_menu;
  89. Boolean                    drawAsText;                /* For iconicLDEF()     */
  90. int                            hOffset, vOffset;
  91.  
  92. void                        main(void);
  93. Boolean                    do_mouse(EventRecord);
  94. Boolean                    handle_events(void);
  95. void                        do_command(long);
  96. void                        setup(void);
  97. void                        open_document(void);
  98. void                        close_document(WindowPtr);
  99. Boolean                    new_document(void *, int);
  100. Boolean                    initialize_list(WindowPtr);
  101. void                        read_icons(WindowPtr, int);
  102.  
  103. #if FORMAT == FAKE_RESOURCE
  104. void                        setup_LDEF(int);
  105. #endif
  106. #if FORMAT == COMPILED
  107. void                        add_LDEF(ListHandle);
  108. void                        remove_LDEF(ListHandle);
  109. #endif
  110. void                        iconicLDEF();
  111.  
  112. /*
  113.  * main()
  114.  * Initialize the program and run the event loop.
  115.  */
  116. void
  117. main()
  118. {
  119.         EventRecord            event;
  120.         WindowPtr                window;
  121.         GrafPtr                    save_port;
  122.         Rect                        box;
  123.  
  124.         setup();
  125.         for (;;) {
  126.             SystemTask();
  127.             while (GetNextEvent(everyEvent, &event)
  128.                  && event.what != nullEvent) {
  129.                 if (event.what == activateEvt
  130.                  || event.what == updateEvt)
  131.                      window = (WindowPtr) event.message;
  132.                 else {
  133.                     window = FrontWindow();
  134.                 }
  135.                 switch (event.what) {
  136.                 case mouseDown:
  137.                     do_mouse(event);
  138.                     break;
  139.                 case activateEvt:
  140.                     if (isOurWindow(window)) {
  141.                         SetPort(window);    /* Or InvalRect crashes!    */
  142.                         LActivate(
  143.                              event.modifiers & activeFlag,
  144.                              DOC.list
  145.                         );
  146.                         /*
  147.                          * For some reason, LActivate doesn't redraw
  148.                          * the scroll bars.  The correct solution
  149.                          * is left as a puzzle for the reader.
  150.                          */
  151.                         if (event.modifiers & activeFlag) {
  152.                             ControlHandle    handle;
  153.                             Rect                    box;
  154.                             
  155.                             handle = (**DOC.list).vScroll;
  156.                             if (handle != NIL) {
  157.                                 box = (**handle).contrlRect;
  158.                                 InvalRect(&box);
  159.                             }
  160.                         }
  161.                             
  162.                     } 
  163.                     break;
  164.                 case updateEvt:
  165.                     if (isOurWindow(window)) {
  166.                         GetPort(&save_port);
  167.                         SetPort(window);
  168.                         BeginUpdate(window);
  169.                         EraseRect(&window->portRect);
  170.                         box = (**DOC.list).rView;
  171.                         InsetRect(&box, -1, -1);
  172.                         FrameRect(&box);
  173.                         LDoDraw(TRUE, DOC.list);
  174.                         LUpdate(window->visRgn, DOC.list);
  175.                         EndUpdate(window);
  176.                         SetPort(save_port);
  177.                     }
  178.                     break;
  179.                 default:
  180.                     break;
  181.                 }
  182.             }
  183.         }
  184. }
  185.  
  186. /*
  187.  * do_mouse(event)
  188.  * Process a mouse button press, calling handlers as
  189.  * needed.
  190.  */
  191. static Boolean
  192. do_mouse(event)
  193. EventRecord        event;
  194. {
  195.         WindowPtr            window;
  196.         register int    which_part;
  197.         Rect                    box;
  198.         int                        item;
  199.         Point                    mouse;
  200.         int                        result;
  201.         long                    new, choice;
  202.         Str255                name;
  203.         GrafPtr                save_port;
  204.         
  205.         which_part = FindWindow(event.where, &window);
  206.         switch (which_part) {
  207.         case inDesk:
  208.             SysBeep(2);
  209.             break;
  210.         case inMenuBar:
  211.             choice = MenuSelect(event.where);
  212.             item = LoWord(choice);
  213.             switch (HiWord(choice)) {
  214.             case MENU_Apple:
  215.                 GetItem(apple_menu, item, &name);
  216.                 if (item == Apple_About)
  217.                     SysBeep(10);                /* No List About                    */
  218.                 else {
  219.                     GetPort(&save_port);
  220.                     OpenDeskAcc(name);
  221.                     SetPort(save_port);
  222.                 }
  223.                 break;
  224.             case MENU_File:
  225.                 window = FrontWindow();
  226.                 switch (item) {
  227.                 case File_Open:
  228.                     open_document();
  229.                     break;
  230.                 case File_Close:
  231.                     close_document(window);
  232.                     break;
  233.                 case File_Debug:
  234.                     Debugger();
  235.                     break;
  236.                 case File_DrawAsText:
  237.                     drawAsText = !drawAsText;
  238.                     CheckItem(file_menu, File_DrawAsText, drawAsText);
  239.                     if (isOurWindow(window))
  240.                         InvalRect(&(*window).portRect);
  241.                     break;
  242.                 case File_Quit:
  243.                     ExitToShell();
  244.                 }
  245.                 default:
  246.                     break;
  247.             }
  248.             HiliteMenu(0);
  249.             break;
  250.         case inDrag:
  251.             box = screenBits.bounds;
  252.             box.top += GetMBarHeight();
  253.             InsetRect(&box, 4, 4);
  254.             DragWindow(window, event.where, &box);
  255.             break;
  256.         case inContent:
  257.             if (FrontWindow() != window)
  258.                 SelectWindow(window);
  259.             else {
  260.                 SetPort(window);
  261.                 if (isOurWindow(window)) {
  262.                     mouse = event.where;
  263.                     GlobalToLocal(&mouse);
  264.                     result = LClick(mouse, event.modifiers, DOC.list);
  265.                     (void) LLastClick(DOC.list);
  266.                 }
  267.             }
  268.             break;
  269.         case inGoAway:
  270.             if (isOurWindow(window)
  271.              && TrackGoAway(window, event.where))
  272.                     close_document(window);
  273.             break;
  274.         }
  275.         return (FALSE);
  276. }
  277.  
  278. /*
  279.  * open_document()
  280.  * Ask for a file (allow all files).  Open its resource
  281.  * fork (if possible).  If we succeed, create a new
  282.  * window and look for all ICN# resources.
  283.  */ 
  284. void
  285. open_document()
  286. {
  287.         SFReply                    reply;
  288.         int                            file;
  289.         static Point        where = { 85, 85 };
  290.  
  291.         SFGetFile(
  292.             where,                                    /* Where on the screen        */
  293.             NIL,                                        /* Unused                                    */
  294.             NIL,                                        /* no file filter                    */
  295.             -1,                                            /* Allow all file types        */
  296.             NIL,                                        /* … thus no typeList            */
  297.             NIL,                                        /* no dialog hook                    */
  298.             &reply                                    /* reply goes here                */
  299.         );
  300.         if (reply.good) {
  301.             SetVol(NIL, reply.vRefNum);
  302.             SetCursor(*GetCursor(watchCursor));
  303.             if ((file = OpenResFile(reply.fName)) == -1)
  304.                 SysBeep(10);                    /* No resource fork                */
  305.             else {
  306.                 if (new_document(reply.fName, file) == FALSE)
  307.                     SysBeep(10);                /* No memory                            */
  308.                 CloseResFile(file);
  309.             }
  310.             SetCursor(&arrow);
  311.         }
  312. }
  313.  
  314. /*
  315.  * close_document()
  316.  * Close the document in the current (front) window.
  317.  * Dump the handles that were stored in the list's cells.
  318.  */
  319. void
  320. close_document(window)
  321. WindowPtr            window;
  322. {
  323.         IconInfo        iconInfo;
  324.         short                size;
  325.         Cell                cell;
  326.  
  327.         if (isOurWindow(window) == FALSE)
  328.             Debugger();
  329.         SetCursor(*GetCursor(watchCursor));
  330.         /*
  331.          * Iterate over all cells in the list.
  332.          */
  333.         cell.h = cell.v = 0;
  334.         do {
  335.             size = sizeof iconInfo;
  336.             LGetCell(&iconInfo, &size, cell, DOC.list);
  337.             if (size == sizeof iconInfo)    /* Non-empty cell?    */
  338.                 DisposHandle(iconInfo.handle);
  339.         } while (LNextCell(TRUE, TRUE, &cell, DOC.list));
  340. #if FORMAT == COMPILED
  341.         remove_LDEF(DOC.list);
  342. #endif
  343.         LDispose(DOC.list);
  344.         CloseWindow(window);
  345.         DisposPtr(window);
  346.         SetCursor(&arrow);
  347. }
  348.  
  349. /*
  350.  * setup()
  351.  * One-time initialization.
  352.  */
  353. void
  354. setup()
  355. {
  356.         InitGraf(&thePort);
  357.         InitFonts();
  358.         FlushEvents(everyEvent, 0);
  359.         InitWindows();
  360.         InitMenus();
  361.         TEInit();
  362.         InitDialogs(NIL);
  363.         InitCursor();
  364.         MaxApplZone();
  365.         apple_menu = NewMenu(MENU_Apple, "\p\024");
  366.         file_menu = NewMenu(MENU_File, "\pFile");
  367.         AppendMenu(apple_menu, "\p(No List Demo About;(-");
  368.         AddResMenu(apple_menu, 'DRVR');
  369.         AppendMenu(
  370.             file_menu,
  371.             "\pOpen\311/O;Close;Draw As Text;Debug/.;(-;Quit/Q"
  372.         );
  373.         InsertMenu(apple_menu, 0);
  374.         InsertMenu(file_menu, 0);
  375.         DrawMenuBar();
  376. #if FORMAT == FAKE_RESOURCE
  377.         setup_LDEF(LDEF_ID);
  378. #endif
  379.         if (new_document("\pList Demo", -1) == FALSE) {
  380.             SysBeep(10);
  381.             ExitToShell();
  382.         }
  383. }
  384.  
  385. /*
  386.  * new_document()
  387.  * Build a document: get memory for the WindowRecord and
  388.  * our attached information.  Offset the window with
  389.  * respect to other windows and make the window.  If
  390.  * this succeeds, initialize the document's list.  If
  391.  * that succeeds, read the icons.
  392.  */
  393. Boolean
  394. new_document(title, resFile)
  395. void            *title;                    /* Pascal string                            */
  396. int                resFile;                /* Open resource file, if any    */
  397. {
  398.         WindowPtr            window;
  399.         DocumentPtr        doc;
  400.         Rect                    box;
  401.         static long        sequence;        /* Identify windows                */
  402.         
  403.         doc = (DocumentPtr) NewPtr(sizeof (DocumentRecord));
  404.         if (doc == NIL)
  405.             return (FALSE);
  406.         /*
  407.          * Locate the window and get its shape.  This could
  408.          * probably be done better.
  409.          */
  410.         box.left = 0;
  411.         box.top = GetMBarHeight() * 2;
  412.         box.right = box.left
  413.                             + (iconSize * iconCols)
  414.                             + sBarWidth
  415.                             + 2;
  416.         box.bottom = box.top
  417.                             + (iconSize * iconRows)
  418.                             + 2;
  419.         OffsetRect(&box, hOffset, vOffset); 
  420.         if (box.bottom > screenBits.bounds.bottom
  421.          || box.right > screenBits.bounds.right) {
  422.              OffsetRect(&box, -hOffset, -vOffset);
  423.              hOffset = 0;
  424.              vOffset = 0;
  425.         }
  426.         hOffset += hOffsetDelta;
  427.         if (hOffset >= hOffsetMax)
  428.             hOffset = 0;
  429.         vOffset += vOffsetDelta;
  430.         if (vOffset >= vOffsetMax)
  431.             vOffset = 0;
  432.         window = NewWindow(
  433.                     doc,                                /* Allocated storage            */
  434.                     &box,                                /* Display Rect                        */
  435.                     title,                            /* Title                                    */
  436.                     TRUE,                                /* Visible on creation        */
  437.                     noGrowDocProc,            /* Window type                        */
  438.                     -1L,                                /* Show in front                    */
  439.                     TRUE,                                /* GoAway box                            */
  440.                     ++sequence                    /* RefCon    (debug only)        */
  441.                 );
  442.         if (window == NIL) {
  443.             DisposPtr(doc);
  444.             return (FALSE);
  445.         }
  446.         if (initialize_list(window) == FALSE) {
  447.             CloseWindow(window);
  448.             DisposPtr(doc);
  449.             return (FALSE);
  450.         }
  451.         SetPort(window);
  452.         TextFont(applFont);
  453.         TextSize(9);
  454.         read_icons(window, resFile);
  455.         return (TRUE);
  456. }
  457.  
  458. /*
  459.  * initialize_list()
  460.  * Build a list whose cells will hold our icon records.
  461.  * If our LDEF is completely compiled, call add_LDEF
  462.  * after creation.
  463.  */
  464. Boolean
  465. initialize_list(window)
  466. WindowPtr            window;
  467. {
  468.         int                    type;
  469.         Handle            handle;
  470.         int                    *jump;
  471.         Rect                box;
  472.         Point                cell;
  473.         Rect                dimension;
  474.         
  475.         box = (*window).portRect;
  476.         InsetRect(&box, 1, 1);            /* Room for frame                */
  477.         box.right -= sBarWidth;
  478.         SetPt(&cell, iconSize, iconSize);
  479.         box.bottom =
  480.             box.top + (height(box) / cell.v) * cell.v;
  481.         box.right =
  482.             box.left + (width(box) / cell.h) * cell.h;
  483.         SetRect(&dimension, 0, 0, box.right / cell.h, 0);
  484.         DOC.list = LNew(
  485.             &box,                                        /* Display rectangle            */
  486.             &dimension,                            /* Shape (rows, cols)            */
  487.             cell,                                        /* Cell shape on screen        */
  488.             LDEF_ID,                                /* List handler, if any        */
  489.             window,                                    /* The window                            */
  490.             TRUE,                                        /* Drawing's ok                        */
  491.             FALSE,                                    /* No grow box                        */
  492.             FALSE,                                    /* No horizontal scroll        */
  493.             TRUE                                        /* Vertical scroll                */
  494.         );
  495.         if (DOC.list == NIL)
  496.             return (FALSE);
  497.         (**DOC.list).selFlags = lOnlyOne;
  498. #if FORMAT == COMPILED
  499.         add_LDEF(DOC.list);
  500. #endif
  501.         (**DOC.list).refCon = (long) iconicLDEF;
  502.         return (TRUE);
  503. }
  504.  
  505. /*
  506.  * read_icons()
  507.  * Fill the list with the icon handles and resource ids.
  508.  */
  509. void
  510. read_icons(window, resFile)
  511. WindowPtr                window;
  512. int                            resFile;
  513. {
  514.         int                    n_icons;
  515.         int                    i;
  516.         int                    n_rows, n_cols;
  517.         Cell                cell;
  518.         ResType            type;
  519.         IconInfo        iconInfo;
  520.         Str255            name;
  521.         
  522.         LDoDraw(FALSE, DOC.list);
  523.         if (resFile != -1) {
  524.             UseResFile(resFile);
  525.             n_icons = Count1Resources(RESOURCE);
  526.         }
  527.         else {
  528.             n_icons = CountResources(RESOURCE);
  529.         }
  530.         n_cols = (**DOC.list).dataBounds.right;
  531.         n_rows = (n_icons + (n_cols - 1)) / n_cols;
  532.         /*
  533.          * Note that we can have empty cells in the last row.
  534.          * The drawing routine must check for this case.
  535.          */
  536.         if (n_rows > 0)
  537.             LAddRow(n_rows, 0, DOC.list);
  538.         for (i = 0; i < n_icons; i++) {
  539.             if (resFile != -1)
  540.                 iconInfo.handle = Get1IndResource(RESOURCE, i + 1);
  541.             else {
  542.                 iconInfo.handle = GetIndResource(RESOURCE, i + 1);
  543.             }
  544.             if (iconInfo.handle == NIL)
  545.                 iconInfo.number = -1;
  546.             else {
  547.                 GetResInfo(
  548.                     iconInfo.handle, &iconInfo.number, &type, name);        
  549.                 DetachResource(iconInfo.handle);
  550.             }
  551.             cell.v = i / n_cols;
  552.             cell.h = i % n_cols;
  553.             LSetCell(&iconInfo, sizeof iconInfo, cell, DOC.list);
  554. #if 0        /* Debug: watch the icons as they're read in        */
  555.             {
  556.                 Rect            rect;
  557.                 SetRect(&rect, 1, 1, 33, 33);
  558.                 PlotIcon(&rect, iconInfo.handle);
  559.             }
  560. #endif
  561.         }
  562.         LDoDraw(TRUE, DOC.list);
  563.         InvalRect(&(**DOC.list).rView);
  564. }
  565.  
  566.